package horde.internalResources.horrorControl.HCvis.components;

import horde.control.AutomatonBehavior.Action;
import horde.control.AutomatonBehavior.State;
import horde.internalResources.Directory;
import horde.internalResources.dictionaries.dictionary;
import horde.patterns.Msg;
import horde.utils.iconFactory.iconFactory;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.EventObject;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

/**
 * Panel that will be contained by every cell of the table of the debug panel.
 * @author Arturo Mazón and Andres Picazo
 */

public class panelCelda extends JPanel implements TableCellRenderer, TableCellEditor, ActionListener{
    
    // <editor-fold defaultstate="collapsed" desc="Atributes">
    private JLabel nameMethod;
    private JLabel srcL,msgL,dstL;
    private JTextField src;
    private JComboBox msgC;
    private JComboBox srcC;
    private JComboBox dstC;
    private JButton execButton;
    private Dimension d = new Dimension(100,200);
    private Dimension d2 = new Dimension(20,40);
    private JPanel namePanel, dataPanel;

    private JTable paramTable;
    private DefaultTableModel modelt;

    private String destination = "";

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Builders">
    public panelCelda(){
        super();
        nameMethod = new JLabel("NAME");
        crearElementos();
        organizarElementos();
        this.setSize(d);
        this.setVisible(true);
    }

    public panelCelda(String name){
        super();
        nameMethod = new JLabel(name);

        crearElementos();
        organizarElementos();
        this.setSize(d);
        this.setVisible(true);
    }

    // </editor-fold>

    /**
     * Creates all the components necessary to build the graphic interface
     */
    private void crearElementos() {
        nameMethod.setForeground(Color.white);
        nameMethod.setOpaque(true);
        nameMethod.setBackground(Color.black);
        srcL = new JLabel(dictionary.getString("hcVis.cellSrc"));
        msgL = new JLabel(dictionary.getString("hcVis.cellMsg"));
        dstL = new JLabel(dictionary.getString("hcVis.cellDst"));
        src = new JTextField();
        msgC = new JComboBox();
        srcC = new JComboBox();
        dstC = new JComboBox();

        setSrcComboBox(Directory.getInstance().getAgentNames());
        srcL.setMaximumSize(d2);
        msgL.setMaximumSize(d2);
        dstL.setMaximumSize(d2);
        
        src.setMaximumSize(d2);
       
        
        namePanel = new JPanel();
        dataPanel = new JPanel();

        modelt = new DefaultTableModel();
        modelt.addColumn(dictionary.getString("hcVis.cellCValue"));
        modelt.addColumn(dictionary.getString("hcVis.cellCType"));
        paramTable = new JTable(){
            @Override public boolean isCellEditable(int row, int column){
                if (column == 1) return false;
                else return true;
            }
        };
        paramTable.setModel(modelt);
        iconFactory ic = new iconFactory();
        execButton = new JButton("",ic.getIcon("iconExec[32x32].PNG"));
        execButton.addActionListener(this);
    }

    /**
     * Places properly each component in the graphic interface
     */
    private void organizarElementos() {
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        namePanel.setBackground(Color.black);
        namePanel.add(nameMethod);
        dataPanel.setLayout(new GridLayout(3,2));
        dataPanel.add(srcL);
        dataPanel.add(srcC);
        dataPanel.add(msgL);
        dataPanel.add(msgC);
        dataPanel.add(dstL);
        dataPanel.add(dstC);
        
        this.setLayout(new BorderLayout());
        this.add(namePanel,BorderLayout.NORTH);
        mainPanel.add(dataPanel,BorderLayout.NORTH);
        JScrollPane scroll = new JScrollPane(paramTable);
        mainPanel.add(scroll,BorderLayout.CENTER);
        mainPanel.add(execButton,BorderLayout.SOUTH);
        this.add(mainPanel,BorderLayout.CENTER);
        
    }

    /**
     * Sets the possible messages that every agent can send as options of the proper Box
     * @param col Set of possible messages
     */
    public void setMsgComboBox(Object[] col){
        for(int i=0;i<col.length;i++){
            State s = (State) col[i];
            Object[] actions = s.getActions();
            for (int j=0;j<actions.length;j++){
                Action a = (Action) actions[j];
                msgC.addItem(a.getRequest());
            }
        }
    }

    /**
     * Sets the possible agents that can work as sources of a message
     * @param col Set of possible sources
     */
    public void setSrcComboBox(ArrayList s){
        for (Object i:s){
            String aux = (String) i;
            srcC.addItem(aux);
            dstC.addItem(aux);

        }
        srcC.addItem("~");
    }

    /**
     * Adds one row for every parameter needed to execute the method chosen and sets for each of them its type.
     * @param m Name of the method
     * @param dst Destination
     */
    public void setDataTable(Method m, String dst){
        Class[] param = m.getParameterTypes();
        for(Class i: param){
            String[] aux = {"",i.getSimpleName()};
            modelt.addRow(aux);
        }
        destination = dst;
    }

    // <editor-fold defaultstate="collapsed" desc="Cell Renderer Management">
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        return (panelCelda) value;
    }

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        return (panelCelda) value;
    }



    public Object getCellEditorValue() {
        return null;
    }

    public boolean isCellEditable(EventObject anEvent) {
        return true;
    }

    public boolean shouldSelectCell(EventObject anEvent) {
        return true;
    }

    public boolean stopCellEditing() {
        return true;
    }

    public void cancelCellEditing() {

    }

    public void addCellEditorListener(CellEditorListener l) {

    }

    public void removeCellEditorListener(CellEditorListener l) {
       
    }

    // </editor-fold>

    /**
     * Method to implements the tasks done by the exec button. It sends a message from a source to a target with a parameters with the options chosen.
     * @param e Action Performed
     */
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == execButton){
            ArrayList a = readParamTable();
            ArrayList params = new ArrayList();
            params.add(msgC.getSelectedItem().toString());
            String aux = "";
            for (int i=0;i<a.size();i = i + 2){
                if (a.get(i+1).equals("Integer")) params.add (new Integer(Integer.parseInt(a.get(i).toString())));
                aux = dictionary.getString("hcVis.cellCValue") + i + " : " + a.get(i) + dictionary.getString("hcVis.cellCType") + i + " : " + a.get(i+1);
            }
            String s = aux;
            System.err.println(s);
            Msg msg;
            if (params.size() == 1) {
                msg = Msg.composeRequest(this.srcC.getSelectedItem().toString(), dstC.getSelectedItem().toString(), msgC.getSelectedItem().toString());
            }
            else {
                msg = Msg.composeRequest(this.srcC.getSelectedItem().toString(), dstC.getSelectedItem().toString(), params.toArray());
            }
            Directory.getInstance().getRequests().post(msg);
        }
    }

    /**
     * Method that extracts all the information from the table of parameters as pairs of Value-Type
     * @return An ArrayList container of all the information of the table of parameters
     */
    private ArrayList readParamTable(){        
        ArrayList outcome = new ArrayList();

        for (int i=0;i<modelt.getRowCount();i++){
            outcome.add((String) modelt.getValueAt(i, 0));
            outcome.add((String) modelt.getValueAt(i, 1));            
        }       

        return outcome;
    }
    
}
